package pri.syl.xiaowu.websocket.netty.server.handler.core.factory;

import pri.syl.xiaowu.websocket.core.container.WebsocketRouteContainer;
import pri.syl.xiaowu.websocket.core.domain.HttpUpgradeRequest;
import pri.syl.xiaowu.websocket.core.domain.builder.HttpUpgradeRequestBuilder;
import pri.syl.xiaowu.websocket.core.exception.WebsocketException;
import pri.syl.xiaowu.websocket.core.factory.UriFactory;
import pri.syl.xiaowu.websocket.core.template.WebsocketRouteTemplate;
import pri.syl.xiaowu.websocket.core.template.core.factory.WebsocketRouteTemplateFactory;
import pri.syl.xiaowu.websocket.netty.server.handler.core.factory.constant.HandshakeFactoryConstant;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;

import java.util.Map;

/**
 * ClassName: HandshakeFactory
 * Description: 握手工厂
 */
public class HandshakeFactory {
    private HandshakeFactory() {
    }

    public static WebsocketRouteTemplate pathValidation(String requestUri) throws WebsocketException {
        return WebsocketRouteContainer.getWebsocketRouteTemplate(UriFactory.conversionRouteUri(requestUri));
    }

    //握手
    public static void handshake(FullHttpRequest request, int maxFramePayloadLength, Channel channel) throws WebsocketException {
        WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
                getWebSocketUrl(request), null, Boolean.TRUE, maxFramePayloadLength);
        WebSocketServerHandshaker wsHandshake = wsFactory.newHandshaker(request);
        if (null == wsHandshake) {
            WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(channel);
            throw new WebsocketException("Handshake Fail");
        }
        wsHandshake.handshake(channel, request);
    }

    //升级管道
    public static void upgradePipeline(WebsocketRouteTemplate websocketRouteTemplate, int readTimeoutMilli, Channel channel, FullHttpRequest request) throws WebsocketException {
        String requestUri = request.uri();
        String route = WebsocketRouteTemplateFactory.getRoute(websocketRouteTemplate);
        Map<String, String> uriVariable = UriFactory.getUriVariable(route, requestUri);
        Map<String, String> uriParamMap = UriFactory.getUriParamMap(requestUri);
        HttpUpgradeRequest httpUpgradeRequest = HttpUpgradeRequestBuilder.builderHttpUpgradeRequest(request.headers(), uriVariable, uriParamMap);
        ChannelPipelineFactory.upgradeWebsocketPipeline(channel, readTimeoutMilli, httpUpgradeRequest, websocketRouteTemplate);
    }

    private static String getWebSocketUrl(FullHttpRequest request) {
        return HandshakeFactoryConstant.WEBSOCKET_PROTOCOL + request.headers().get(HttpHeaderNames.HOST) + request.uri();
    }
}
